<?php
/**
* @link http://framework.org/
* @copyright Copyright: 2003-2004 Doutromundo
* @author Gregory Brown <bugzbrown@gmail.com>
* @access public
* @package addons
*/
/**
* MYSQL Abstraction class
* This class uses simple function to generalize the use of database functions in Framework
* in order to minimize changes in case of a platform change.
* Eventually, we should have this class split into several segments, where each of the segments
* is responsible for handling one type of database. The database is controlled by the config file
* and today only MYSQL databases are supported.
* New features have been added to ensure backward compatability, but queries should now be run with
* execute() instead of makeSelect and execQuery. In version 1.0 backward compatability will be removed.
*
* @link http://framework.org/
* @version 0.7.0
* @copyright Copyright: 2002-2005 Doutromundo
* @author Gregory Brown <bugzbrown@gmail.com>
* @access public
* @package database
* @subpackage dbTypes
*/
class _database{

	/**
	 *
	 * Database connection resource
	 *
	 * @var DatabaseResource
	 */
	var $dbConnection;
	/**
	* Database host
	*
	* @var String
	*/
	var $host;
	/**
	* Database user name
	*
	* @var String
	*/
	var $user;
	/**
	* Database connection pasword
	*
	* @var String
	*/
	var $password;
	/**
	* Database name
	*
	* @var String
	*/
	var $database;
	/**
	* Determine if the conneciton type hould be persistant or not
	*
	* @var Boolean
	*/
	var $persistant;
	/**
	* Result array : Where the associative array of the query is passed back to the user
	*
	* @var Boolean
	*/
	var $resultArray;
	/**
	* Last_id : Returns the last ID generated from an insert query
	*
	* @var Boolean
	*/
	var $last_id=0;
	/**
	* MySQL error number (in case of an error in the query)
	*
	* @var Integer
	*/
	var $errNum;
	/**
	* MySQL error description (in case of an error in the query)
	*
	* @var String
	*/
	var $errDesc;
	/**
	* The ammount of records brought back by a multiple select statement
	*
	* @var Integer
	*/
	var $select_limit;

	// DATABASE RELATED FUCTION
	//
	//
	//
	/**
	*CONSTRUCTOR - using values from config.inc.php
	*@param Boolean $config If set to true(default) loads parameter from the config file, if not, it loads the parameters from the object.
	*@return VOID
	**/
	function _database ( $config=true ){
		if ($config){
			$this->host=DB_HOST;
			$this->user=DB_USER;
			$this->password=DB_PASSWORD;
			$this->database=DB_NAME;
			$this->persistant=false;
			$this->select_limit=DB_LIMIT;
		}else{
			$this->host="";
			$this->user="";
			$this->password="";
			$this->database="";
			$this->persistant=false;
			$this->select_limit=30000;
		}
	}

	/**
	*Connect to the database.
	*In case of an error, the errNum and errDesc are filled.
	*@return Boolean
	**/
	function connect(){
		/* Connecting, selecting database */

		if (!$this->persistant){
			$this->dbConnection = mysql_connect($this->host, $this->user, $this->password);
		}else{
			$this->dbConnection = mysql_connect($this->host, $this->user, $this->password);
		}
		mysql_select_db($this->database, $this->dbConnection);

		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;

		}else{
			return true;
		}
	}

	/**
	*Executes a query with no return (Insert, update, delete).
	*In case of an error, the errNum and errDesc are filled.
	*@return Boolean
	**/
	function execQuery($query){
		/* Performing SQL query */
		$result = mysql_query($query,$this->dbConnection);
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			$checkSelect=strpos(strtolower($query),"insert");
			if (is_numeric($checkSelect)&& $checkSelect<6){
				$this->last_id = $this->lastInsertID();
			}else{
				$this->last_id = 0;
			}
			return true;
		}
	}
	/**
	*Retrieve the last Inserted ID from MySQL
	*In case of an error, the errNum and errDesc are filled and false is returned
	*@return Integer/Boolean
	**/
	function lastInsertID(){
		$id = @mysql_insert_id($this->dbConnection);
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			return $id;
		}
	}

	/**
	*Initiate a transaction
	*Should only be used with a persistant connection (but it does work with a non persistant sometimes)
	*@return Boolean
	**/
	function trnsBegin() {
		// transaction begin
		mysql_query("BEGIN",$this->dbConnection);
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			return true;
		}
	}

	/**
	*Rollback a transaction
	*Should only be used with a persistant connection (but it does work with a non persistant sometimes)
	*@return Boolean
	**/
	function trnsRollback() {
		// transaction rollback
		mysql_query("ROLLBACK",$this->dbConnection);
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			return true;
		}
	}

	/**
	*Commit a transaction
	*Should only be used with a persistant connection (but it does work with a non persistant sometimes)
	*@return Boolean
	**/
	function trnsCommit() {
		// transaction commit
		mysql_query("COMMIT",$this->dbConnection);
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			return true;
		}
	}

	/**
	*Make an associative array from a select
	*Sets $resultArray to the result of the query in an associative array in this format array[row][field]
	*The field receives the name of the field in the sql statement or in the database.
	*@return Boolean
	**/
	function makeSelectArray($sql){
		// Busca um array com os valores do select
		$arMakeSelect = Array();
		$result = mysql_query($this->check_sql($sql),$this->dbConnection) ;
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			$count_line=0;
			while ($line = mysql_fetch_array($result)) {
				$count_row=0;
				foreach ($line as $col_value) {
					$arMakeSelect[$count_line][key($line)]=$col_value;
					$count_row++;
					next($line);
				}
				$count_line++;
			}
			$this->resultArray =  $arMakeSelect;
			return true;
		}
	}

	/**
	*Make an associative array from a select
	*Sets $resultArray to the result of the query in an associative array in this format array[row][field]
	*The field receives the name of the field in the sql statement or in the database.
	*@return Boolean
	**/
	function makeSingleSelectArray($sql){
		// Busca um array com os valores do select
		$arMakeSelect = Array();

		// get old limit
		$old_limit=$this->select_limit;
		// set new limit
		$this->select_limit=1;

		$result = mysql_query($this->check_sql($sql),$this->dbConnection) ;

		// set old limit again
		$this->select_limit=$old_limit;

		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			$count_line=0;
			while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
				foreach ($line as $col_value) {
					$arMakeSelect[key($line)]=$col_value;
					next($line);
				}
			}
			$this->resultArray =  $arMakeSelect;
			return true;
		}
	}

	/**
	*Close connection to DB
	*@return Boolean
	**/
	function close(){
		// fecha a conexao com o DB
		mysql_close($this->dbConnection);
		if (mysql_errno()>0){
			$this->errNum = mysql_errno();
			$this->errDesc = mysql_error();
			return false;
		}else{
			return true;
		}

	}

	/**
	 * CHECK SQL
	 * Make sure that the SQL statement contains a limit clause to minimize the overhead on the MySQL server.
	 * This function will check for a LIMIT statement in a SELECT CLAUSE ONLY
	 *
	 * @param unknown $sql
	 * @return unknown
	 */
	function check_sql($sql){
		if (strpos(strtolower($sql),"limit")<3){
			// we will need to add a limit if this is a select
			if (strpos(strtolower($sql),"select")<3){
				$sql .=" LIMIT 0,$this->select_limit";
			}
		}
		return $sql;
	}

	/**
	 * EXECUTE A QUERY
	 * The execute query will by default return a recordset array with N rows, only in cases where defined it will
	 * return a single array with the name and values of the columns
	 * or return a void statement.
	 * the function will always return a BOOLEAN in order to state that the connection ran smoothly or not
	 *
	 * @param integer $execType
	 */
	function execute($sql,$execType=1){
		$newcon=false;
		if (!$this->dbConnection){
			// we have no connection
			if ($this->connect()){
				$newcon=true;
			}
		}

		switch ($execType) {
			case 0:
				$resreturn = $this->makeSingleSelectArray($sql);
				break;
			case 2:
				$resreturn = $this->execQuery($sql);
				break;

			default:
				$resreturn = $this->makeSelectArray($sql);
				break;
		}
		if ($newcon){
			// we created a new connection so we close it
			$this->close();
		}
		return $resreturn;
	}
}
// DEFINITION OF QUERY TYPES
define("DB_SINGLE_RETURN","0");
define("DB_MULTIPLE_RETURN","1");
define("DB_NO_RETURN","2");

?>